<template>
  <div>
    <el-form
      label-width="80px"
      :model="spu"
      :rules="rules"
      ref="form"
      :disabled="operator === 'lookSpu'"
    >
      <el-form-item label="SPU名称" placeholder="请输入SPU名称" prop="spuName">
        <el-input v-model="spu.spuName"></el-input>
      </el-form-item>
      <el-form-item label="SPU品牌" prop="tmId">
        <el-select placeholder="请选择SPU品牌" v-model="spu.tmId">
          <el-option
            v-for="tm in trademarkList"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item
        label="SPU描述"
        placeholder="请输入SPU描述"
        prop="description"
      >
        <el-input
          type="textarea"
          :rows="2"
          v-model="spu.description"
        ></el-input>
      </el-form-item>
      <el-form-item label="SPU图片" prop="spuImageList">
        <!-- :class="{ 'spu-form-upload': spu.spuImageList.length > 5 }" -->
        <el-upload
          :limit="5"
          :disabled="operator === 'lookSpu'"
          :action="`${this.baseUrl}/admin/product/fileUpload`"
          list-type="picture-card"
          :file-list="spuImageFileList"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
          accept="image/jpeg,image/png"
        >
          <!-- 
          方法1：通过样式来限制照片不能选着太多，element没有提供功能，自己通过给添加动态样式
           给.el-upload 添加一个父类样式来控制el-upload显示
            el-upload由于scoped的作用，不能设置全局elementui的样式，所以要加一个父类样式控制
            方法2：直接加一个：limit='5'限制上传5张
         -->
          <i class="el-icon-plus"></i>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible">
          <img width="100%" :src="dialogImageUrl" alt="" />
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select
          v-model="baseSaleAttrId"
          :placeholder="`还剩${filterSelectList.length}个属性值`"
        >
          <el-option
            v-for="saleAttr in filterSelectList"
            :key="saleAttr.id"
            :label="saleAttr.name"
            :value="saleAttr.id"
          ></el-option>
        </el-select>
        <el-button
          class="el-icon-plus"
          type="primary"
          :disabled="!baseSaleAttrId"
          @click="addSaleName"
        >
          添加属性值
        </el-button>
        <el-table
          :data="spu.spuSaleAttrList"
          border
          style="width: 100%"
          class="sale-margin"
        >
          <el-table-column
            type="index"
            label="序号"
            width="80"
            align="center"
          ></el-table-column>
          <el-table-column
            label="属性名"
            prop="saleAttrName"
            width="100"
          ></el-table-column>
          <el-table-column label="属性值列表" prop="spuSaleAttrValueList">
            <template v-slot="{ row, $index }">
              <!-- 便利展示数据 -->
              <el-tag
                class="spu-tag"
                v-for="(value, i) in row.spuSaleAttrValueList"
                :key="i"
                closable
                type="success"
                @close="handleClose(row, i)"
              >
                {{ value.saleAttrValueName }}
              </el-tag>
              <el-button
                class="el-icon-plus"
                type="success"
                size="mini"
                v-show="!row.isEdit"
                @click="addSaleAttrValue(row, $index)"
              >
                添加
              </el-button>
              <el-input
                min
                :ref="$index"
                size="mini"
                v-show="row.isEdit"
                v-model="tempValueName"
                @blur="setSaleAttrValue(row, $index)"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template v-slot="{ row, $index }">
              <el-tooltip content="删除属性" placement="top">
                <el-button
                  type="danger"
                  class="el-icon-delete"
                  @click="delSaleAttrValue(row, $index)"
                ></el-button>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
    <el-button type="primary" @click="saveSpu">确定</el-button>
    <el-button @click="cancel">取消</el-button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
import { reqTrademarkShowSpu } from '@/api/production/trademark'
import {
  reqBaseSaleAttrList,
  reqSaveSpuInfo,
  reqGetSpuById,
  reqUpdateSpuInfo
} from '@/api/production/spu'
import { reqSpuImageList } from '@/api/production/sku'
export default {
  name: 'UpdateOrLook',
  // 添加某一个品牌下的商品
  data() {
    let validator = (rule, value, callback) => {
      /* 
      rule 规则名称 ，包含字段
      value 校验值的情况
      callback 必须要调用
        callback () 通过
        callback(xxx) 失败
       */

      if (!this.spu.spuSaleAttrList.length) {
        callback('至少添加一个属性')
        return
      }
      // 每个销售属性都要添加至少一个属性值
      const isEveryHasValue = this.spu.spuSaleAttrList.every(
        item => item.spuSaleAttrValueList.length
      )
      if (!isEveryHasValue) {
        callback('每个销售属性的值最少有一个')
        return
      }
      callback()
    }
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      baseUrl: process.env.VUE_APP_BASE_API,
      trademarkList: [], //品牌下来表
      baseSaleAttrId: '', //临时收集baseSaleAttrId的值
      selectList: [], //存放获取到的属性列表
      // 添加属性值的列表，随着选中长度而减小
      tempValueName: '', //临时存放属性值
      spu: {
        spuName: '', //商品spu名称
        description: '', //商品spu描述
        tmId: '', //品牌id
        spuImageList: [], //品牌照片列表
        /* 
        商品销售属性列表：{
        baseSaleAttrId:选中的 属性值id
        saleAttrName: tempSaleAttrName.name,
        // 初始化出来一个数组变成响应式
        spuSaleAttrValueList: [{ saleAttrName: "", saleAttrValueName: "" }],
      }
         */
        spuSaleAttrList: []
      },
      rules: {
        spuName: [
          { required: true, message: '请输入SPU名称', trigger: 'blur' }
        ],
        description: [
          { required: true, message: '请输入SPU描述', trigger: 'blur' }
        ],
        tmId: [{ required: true, message: '请输入SPU描述', trigger: 'change' }],
        spuImageList: [
          { required: true, message: '请上传SPU照片', trigger: 'blur' }
        ],
        // 自定义规则，添加属性不能为空，每一项属性值列表每一个对象值不能为空
        spuSaleAttrList: [{ required: true, validator: validator }]
      },
      spuImageFileList: [] //仅仅为了展示图片，不用计算属性添加uid
    }
  },
  async mounted() {
    let res = await Promise.allSettled([
      reqTrademarkShowSpu(),
      reqBaseSaleAttrList()
    ])
    this.trademarkList = res[0].value
    this.selectList = res[1].value
  },
  computed: {
    ...mapState('category', ['category3Id']),
    ...mapState('spu', ['spuId', 'operator']),

    // 对selectList数组进行过滤，让其显示还有几个数据，一开始是可以通过selectList的length进行计算
    // 但是修改的话在这个基础上过滤掉之前添加的，不需要在下面添加或是删除属性对selectList原数组操作
    // 两个数组对象进行过滤！！！
    filterSelectList() {
      return this.selectList.filter(baseSaleAttr => {
        // 判断selectList.name是否在spu.spuSaleAttrList数组里
        return !this.spu.spuSaleAttrList.some(saleAttr => {
          return saleAttr.saleAttrName === baseSaleAttr.name
        })
      })
    }
  },
  watch: {
    operator: {
      async handler(val) {
        if (val === 'lookSpu' || val === 'updateSpu') {
          // let res = await reqGetSpuById(this.spuId);
          let [spuResp, spuImgListResp] = await Promise.allSettled([
            reqGetSpuById(this.spuId),
            reqSpuImageList(this.spuId)
          ])
          if (spuResp.status === 'fulfilled') {
            this.spu = spuResp.value
          } else {
            this.$message({
              type: 'error',
              message: '获取spu详情列表失败'
            })
          }
          if (spuImgListResp.status === 'fulfilled') {
            this.spu.spuImageList = spuImgListResp.value
            // 仅仅是为了展示图片
            this.spuImageFileList = spuImgListResp.value.map(item => {
              return {
                name: item.imgName,
                url: item.imgUrl
              }
            })
          } else {
            this.$message({
              type: 'error',
              message: '获取spu照片列表失败'
            })
          }
          // 在这就直接对数据精心精心改变
          this.spu = {
            ...this.spu,
            spuImageList: this.spu.spuImageList,
            spuSaleAttrList: this.spu.spuSaleAttrList.map(saleAttr => {
              return {
                ...saleAttr,
                isEdit: false,
                spuSaleAttrValueList: [...saleAttr.spuSaleAttrValueList]
              }
            })
          }
          // 根据销售属性值有多少则执行多少个添加属性值
          this.$refs.form.resetFields()
        }
      },
      immediate: true
    }
  },
  methods: {
    ...mapMutations('spu', ['SET_OPERATOR']),
    handleRemove(file, fileList) {
      // 1. 移除照片逻辑
      // 1.1 为了复用，修改显示照片要在upload 添加 :file-list ,但是对照片命名有要求必须是name ，url
      // 需要计算属性spuImageFileList,对数据进行map
      // 1.2 在删除的时候有一次在对数据进行map,变成之前添加的模式命名要加上uid是避免闪屏 uid是这个图片的唯一表示符，

      // this.spu.spuImageList = fileList.map(file => {
      //   return {
      //     imgUrl: file.url,
      //     imgName: file.name,
      //     uid: file.uid //避免闪屏
      //   }
      // })
      // 删除直接是删除即可，展示的照片，但是会闪屏,
      // 是因为一开始我的spuImageList没有uid,经过计算属性之后，有了uid,前者(undefined)和后者uid（是upload组件加的）二者会有替换的效果，所以才会出现闪屏效果，还是采取上面的做法
      // this.spu.spuImageList = this.spu.spuImageList.filter(item => {
      //   // console.log(item.uid)
      //   // item.uid = item.imgUrl + 1 //自己加上唯一表示uid,第一次会出现闪屏，但之后就不会出现闪屏效果，因为一开始我计算属性添加的有uid,但是和我第一次是删除之后出现的uid不一样，第一次会冲突，之后就不会了
      //   return item.imgUrl !== file.url
      // })

      this.spu.spuImageList = fileList.map(file => {
        return {
          imgUrl: file.url,
          imgName: file.name
          // uid: file.uid //uid可以不用加，避免闪屏
          // 遇到问题：当不修改照片时，此时的this.spu.spuImageList列表为空的
          //
        }
      })
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    //图片上传成功
    handleAvatarSuccess(file, fileList) {
      this.spu.spuImageList.push({ imgName: fileList.name, imgUrl: file.data })
      // 修改照片
      // 清空图片表单校验结果
      this.$refs.form?.clearValidate(['spuImageList'])
    },
    // 图片提交之前
    beforeAvatarUpload(file) {
      let imgType = ['image/jpeg', 'image/png', 'image/jpg']
      const isQualify = imgType.indexOf(file.type) !== -1
      const isLt = file.size / 1024 < 500

      if (!isQualify) {
        this.$message.error('上传头像图片只能是 JPG,PNG,JPG 格式!')
      }
      if (!isLt) {
        this.$message.error('上传头像图片大小不能超过 500KB!')
      }
      return isQualify && isLt
    },
    // 1.添加销售属性的名字
    addSaleName() {
      let { selectList } = this
      // 1.1找到点击的值对象,或者在options收集数据的时候就把value和id收集到
      let tempSaleAttrName = selectList.find(
        tm => tm.id === this.baseSaleAttrId
      )
      // console.log(tempSaleAttrName.name);
      //1.2点击之后的selectList长度变
      // this.selectList = this.selectList.filter(
      //   item => item !== tempSaleAttrName
      // )

      // 1.3添加一个空对象
      this.spu.spuSaleAttrList.push({
        baseSaleAttrId: +this.baseSaleAttrId,
        saleAttrName: tempSaleAttrName.name,
        // 初始化出来一个数组变成响应式
        spuSaleAttrValueList: [],
        isEdit: false
      })
      // console.log('baseSaleAttrId', this.baseSaleAttrId)
      //1.4 最后才清空当前的值
      this.baseSaleAttrId = ''
    },
    // 2点击添加属性值,出现input变成编辑状态
    addSaleAttrValue(row, index) {
      // 2.1变成编辑模式
      row.isEdit = true
      // 2.2聚焦
      this.$nextTick(() => {
        this.$refs[index].focus()
      })
    },
    // 3.编辑模式->显示
    setSaleAttrValue(row, index) {
      // 如果值为空则删掉
      if (!this.tempValueName) {
        row.spuSaleAttrValueList.splice(index, 1)
        row.isEdit = false
        return
      }

      // 添加到spuSaleAttrValueList
      row.spuSaleAttrValueList.push({
        baseSaleAttrId: +row.baseSaleAttrId,
        saleAttrName: row.saleAttrName,
        saleAttrValueName: this.tempValueName
      })
      // 出现数值
      row.isEdit = false
      // 清空临时值
      this.tempValueName = ''
    },
    // 4.tag删除
    handleClose(row, index) {
      row.spuSaleAttrValueList.splice(index, 1)
    },
    // 5.删除销售属性，当前行数据数据删掉，selectList长度变成以前一样
    delSaleAttrValue(row, index) {
      // 5.1删掉当前行
      this.spu.spuSaleAttrList.splice(index, 1)
      // 5.2selectList长度变成以前一样,根据id进行排序
      // this.selectList.push({
      //   id: +row.baseSaleAttrId,
      //   name: row.saleAttrName
      // })
      // this.selectList.sort((a, b) => a.id - b.id)
    },
    // 6.点击确定，整体表单校验，校验成功，发送请求
    saveSpu() {
      this.$refs.form.validate(async vali => {
        if (vali) {
          let data = { ...this.spu, category3Id: this.category3Id }
          if (this.operator === 'updateSpu') {
            await reqUpdateSpuInfo(data)
          } else if (this.operator === '') {
            await reqSaveSpuInfo(data)
          }
          this.$message({
            type: 'success',
            message: `${this.operator ? '修改' : '添加'}SPU成功`
          })
          this.cancel()
        }
      })
    },
    // 取消
    cancel() {
      // 清空数据和表单校验
      this.$refs.form.resetFields()
      // 页面跳转
      this.$emit('updateIsShow', 1)
      // 把操作页面显示的改来
      this.SET_OPERATOR('')
    }
  }
}
</script>

<style scoped>
.sale-margin {
  margin: 20px 0;
}
.spu-tag {
  margin: 0 5px;
}
.el-input {
  width: 150px;
}
</style>
